#pragma once

#include <iostream>
#include <memory>
#include <json/json.h>
using namespace std;

// #define SelfDefine 1

namespace Protocol
{

    // 1. 结构化数据的序列和反序列化
    // 2. 用户区分报文边界问题————数据报粘包问题

    // 1. 自定义协议
    // 2. 成熟方案序列和反序列化json/protobuf/xml

    const string ProtSep = " "; // 有效载荷的分隔符
    const string LineBreakSep = "\n";

    string Encode(const string &message) // message是有效载荷
    {
        string len = std::to_string(message.size());
        string package = len + LineBreakSep + message + LineBreakSep;
        return package;
    }

    // 无法保证package是一个独立的完整的报文
    // l
    // len
    // len\n
    // len\nx
    //...
    // 可能不同情况
    // len\nx op y\nlen\nx op y\n
    //...
    bool Decode(string &package, string *message)
    {
        // 除了解包，还要判断报文完整性
        auto pos = package.find(LineBreakSep);
        if (pos == std::string::npos)
            return false;
        string lens = package.substr(0, pos);
        int messagelen = std::stoi(lens);
        int total = lens.size() + messagelen + 2 * LineBreakSep.size();
        if (package.size() < total)
            return false;
        // 现在能保证package内部至少有一个完整的报文了
        *message = package.substr(pos + LineBreakSep.size(), messagelen);
        package.erase(0, total); // 把已经解析完的那部分从原始数据中删掉
        return true;
    }

    class Request
    {
    public:
        Request()
            : _data_x(0), _data_y(0), _oper(0)
        {
        }
        Request(int x, int y, char op)
            : _data_x(x), _data_y(y), _oper(op)
        {
        }
        void Debug()
        {
            cout << "_data_x" << _data_x << endl;
            cout << "_data_y" << _data_y << endl;
            cout << "_oper" << _oper << endl;
        }
        void Inc()
        {
            _data_x++;
            _data_y++;
        }
        // 序列化，结构化数据->字符串
        //  大部分工作都是字符串处理
        bool serialize(string *out)
        {
#ifdef SelfDefine
            *out = std::to_string(_data_x) + ProtSep + _oper + ProtSep + std::to_string(_data_y);
            return true;

#else
            Json::Value root;
            root["datax"] = _data_x;
            root["datay"] = _data_y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }
        // 反序列化
        bool deserialize(string &in) // "x op y"
        {
#ifdef SelfDefine
            auto left = in.find(ProtSep);
            if (left == std::string::npos)
                return false;
            auto right = in.rfind(ProtSep);
            if (right == std::string::npos)
                return false;
            _data_x = std::stoi(in.substr(0, left));
            _data_y = std::stoi(in.substr(right + ProtSep.size()));
            std::string oper = in.substr(left + ProtSep.size(), right - (left + ProtSep.size()));
            if (oper.size() != 1)
                return false;
            _oper = oper[0];
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in,root);
            if(res)
            {
                _data_x = root["datax"].asInt();
                _data_y = root["datay"].asInt();
                _oper = root["oper"].asInt();
            }
            return res;
#endif
        }
        int GetX() { return _data_x; }
        int GetY() { return _data_y; }
        char GetOper() { return _oper; }

    private:
        // 约定格式: _data_y _oper _data_x
        int _data_x; // 第一个参数
        int _data_y; // 第二个参数
        char _oper;  // + - * / %
        // 定协议： "len\nx op y\n" ————报文的自描述字段,\n不属于报文的一部分，约定,第一个\n作为报头len和报文的分隔符，第二个只是方便打印
    };

    class Response
    {
    public:
        Response()
            : _result(0), _code(0)
        {
        }
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }
        // 序列化
        bool serialize(string *out)
        {
#ifdef SelfDefine

            *out = std::to_string(_result) + ProtSep + std::to_string(_code);
            return true;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }
        // 反序列化
        bool deserialize(string &in) // "result code"
        {
#ifdef SelfDefine

            auto pos = in.find(ProtSep);
            if (pos == std::string::npos)
                return false;
            _result = std::stoi(in.substr(0, pos));
            _code = std::stoi(in.substr(pos + ProtSep.size()));
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if(res)
            {
                _result = root["result"].asInt();
                _code = root["code"].asInt();
            }
            return res;
#endif
        }
        void SetResult(int res) { _result = res; }
        void SetCode(int code) { _code = code; }
        int GetResult() { return _result; }
        int GetCode() { return _code; }

    private:
        int _result; // 运算结果
        int _code;   // 运算状态
        // "len\nresult code\n"定协议
    };

    // 简单的工厂模式, 建造类设计模式
    class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();
            return req;
        }
        std::shared_ptr<Request> BuildRequest(int x, int y, int op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, op);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();
            return resp;
        }
        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>(result, code);
            return resp;
        }
    };
}